package com.liuweiheng.base.utils;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import io.micrometer.core.instrument.util.StringUtils;
import org.springframework.http.*;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * HTTP请求工具类
 *
 * @author lwh
 * @date 2021/11/22
 */
public class HttpUtil {

    private static final RestTemplate REST_TEMPLATE;

    static {
        REST_TEMPLATE = new RestTemplate();
    }

    /**
     * 发送JSON格式的POST请求
     * @param url 请求路径
     * @param requestParam 请求参数
     * @param resultClass 返回类型
     * @param <T> 返回类型
     * @return http请求返回内容
     */
    public static <T> T postWithJsonSync(String url, Object requestParam, Class<T> resultClass, Map<String, String> header) {
        // 请求头设置为发送JSON格式数据
        HttpHeaders headers = new HttpHeaders();

        MediaType type = MediaType.parseMediaType("application/json;charset=UTF-8");
        headers.setContentType(type);
        headers.add("Accept", MediaType.APPLICATION_JSON.toString());

        // 设置请求头
        if (null != header && header.size() > 0) {
            for (Map.Entry<String, String> entry : header.entrySet()) {
                headers.add(entry.getKey(), entry.getValue());
            }
        }

        // 封装请求对象参数
        HttpEntity<String> request = new HttpEntity<>(JSONUtil.toJsonStr(requestParam), headers);

        // 发送POST请求，返回值为String(JSON字符串)
        String result = REST_TEMPLATE.postForObject(url, request, String.class);

        // 将返回的JSON字符串转化为对象
        return JSONUtil.toBean(result, resultClass);
    }

    /**
     * 发送JSON格式的POST请求
     * @param url 请求路径
     * @param requestParam 请求参数
     * @param resultClass 返回类型
     * @param <T> 返回类型
     * @return http请求返回内容
     */
    public static <T> T post(String url, Object requestParam, Class<T> resultClass, Map<String, String> header) {
        // 请求头设置为发送JSON格式数据
        HttpHeaders headers = new HttpHeaders();

        MediaType type = MediaType.parseMediaType("application/json;charset=UTF-8");
        headers.setContentType(type);
        headers.add("Accept", MediaType.APPLICATION_JSON.toString());

        // 设置请求头
        if (null != header && header.size() > 0) {
            for (Map.Entry<String, String> entry : header.entrySet()) {
                headers.add(entry.getKey(), entry.getValue());
            }
        }

        // 封装请求对象参数
        HttpEntity<JSONObject> request = new HttpEntity<>(JSONUtil.parseObj(requestParam), headers);

        // 发送POST请求，返回值为String(JSON字符串)
        String result = REST_TEMPLATE.postForObject(url, request, String.class);

        // 将返回的JSON字符串转化为对象
        return JSONUtil.toBean(result, resultClass);
    }

    /**
     * 发送JSON格式的GET请求
     * @param url 请求路径
     * @param resultClass 返回类型
     * @param header 请求头
     * @param <T> 返回类型
     * @return http请求返回内容
     */
    public static <T> T getWithJsonSync(String url, Class<T> resultClass, Map<String, String> header) {
        // 请求头设置为发送JSON格式数据
        HttpHeaders headers = new HttpHeaders();

        // 设置请求头
        if (null != header && header.size() > 0) {
            for (Map.Entry<String, String> entry : header.entrySet()) {
                headers.add(entry.getKey(), entry.getValue());
            }
        }

        headers.setContentType(MediaType.APPLICATION_JSON);

        // 封装请求对象参数
        HttpEntity<String> request = new HttpEntity<>("parameters", headers);

        // 发送GET请求，返回值为String(JSON字符串)
        ResponseEntity<String> result = REST_TEMPLATE.exchange(url, HttpMethod.GET, request, String.class);

        // 将返回的JSON字符串转化为对象
        return JSONUtil.toBean(result.getBody(), resultClass);
    }

    /**
     * 发送JSON格式的PATCH请求
     * @param url 请求路径
     * @param resultClass 返回类型
     * @param header 请求头
     * @param <T> 返回类型
     * @return http请求返回内容
     */
    public static <T> T patchWithJsonSync(String url, Object requestParam, Class<T> resultClass, Map<String, String> header) {
        // 请求头设置为发送JSON格式数据
        HttpHeaders headers = new HttpHeaders();

        MediaType type = MediaType.parseMediaType("application/json;charset=UTF-8");
        headers.setContentType(type);
        headers.add("Accept", MediaType.APPLICATION_JSON.toString());

        RestTemplate restTemplatePatch = new RestTemplate(new HttpComponentsClientHttpRequestFactory());

        // 设置请求头
        if (null != header && header.size() > 0) {
            for (Map.Entry<String, String> entry : header.entrySet()) {
                headers.add(entry.getKey(), entry.getValue());
            }
        }

        // 封装请求对象参数
        HttpEntity<JSONObject> request = new HttpEntity<>(JSONUtil.parseObj(requestParam), headers);

        // 发送请求，返回值为String(JSON字符串)
        ResponseEntity<String> result = restTemplatePatch.exchange(url, HttpMethod.PATCH, request, String.class);

        // 将返回的JSON字符串转化为对象
        return JSONUtil.toBean(result.getBody(), resultClass);
    }

    /**
     * 发送JSON格式的DELETE请求
     * @param url 请求路径
     * @param resultClass 返回类型
     * @param header 请求头
     * @param <T> 返回类型
     * @return http请求返回内容
     */
    public static <T> T delete(String url, Object requestParam, Class<T> resultClass, Map<String, String> header) {
        // 请求头设置为发送JSON格式数据
        HttpHeaders headers = new HttpHeaders();

        MediaType type = MediaType.parseMediaType("application/json;charset=UTF-8");
        headers.setContentType(type);
        headers.add("Accept", MediaType.APPLICATION_JSON.toString());

        RestTemplate restTemplatePatch = new RestTemplate(new HttpComponentsClientHttpRequestFactory());

        // 设置请求头
        if (null != header && header.size() > 0) {
            for (Map.Entry<String, String> entry : header.entrySet()) {
                headers.add(entry.getKey(), entry.getValue());
            }
        }

        // 封装请求对象参数
        HttpEntity<JSONObject> request = new HttpEntity<>(JSONUtil.parseObj(requestParam), headers);

        // 发送请求，返回值为String(JSON字符串)
        ResponseEntity<String> result = restTemplatePatch.exchange(url, HttpMethod.DELETE, request, String.class);

        // 将返回的JSON字符串转化为对象
        return JSONUtil.toBean(result.getBody(), resultClass);
    }

    /**
     * 获取Ip地址
     * @param request HttpServletRequest
     * @return IP
     */
    public static String getIpAddress(HttpServletRequest request) {
        String Xip = request.getHeader("X-Real-IP");
        String XFor = request.getHeader("X-Forwarded-For");
        if(StringUtils.isNotEmpty(XFor) && !"unKnown".equalsIgnoreCase(XFor)){
            //多次反向代理后会有多个ip值，第一个ip才是真实ip
            int index = XFor.indexOf(",");
            if(index != -1){
                return XFor.substring(0,index);
            }else{
                return XFor;
            }
        }
        XFor = Xip;
        if(StringUtils.isNotEmpty(XFor) && !"unKnown".equalsIgnoreCase(XFor)){
            return XFor;
        }
        if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
            XFor = request.getHeader("Proxy-Client-IP");
        }
        if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
            XFor = request.getHeader("WL-Proxy-Client-IP");
        }
        if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
            XFor = request.getHeader("HTTP_CLIENT_IP");
        }
        if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
            XFor = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (StringUtils.isBlank(XFor) || "unknown".equalsIgnoreCase(XFor)) {
            XFor = request.getRemoteAddr();
        }
        return XFor;
    }
}
